#ifndef MENU_CPP
#define MENU_CPP
#include "Menu.h"


void Menu::LoadData()
{	
	int numberOfLibrarians, numberOfBooks, numberOfMembers;
	std::ifstream infile;
	infile.open("library.dat");

	if (infile.good())
	{
		//Beolvassuk a könyvtárosok adatait.
		std::string numberOfLibrariansTemp;
		getline(infile, numberOfLibrariansTemp);
		numberOfLibrarians = atoi(numberOfLibrariansTemp.c_str());

		//Ha nem sikerült a könyvtárosok számának beolvasása, a fájl üres.
		if (infile.eof())
		{
			std::cout << "Librarians not found. Please contact the developer.";
			exit(1);
		}

		for (int i = 0; i < numberOfLibrarians; ++i)
		{
			std::string tmp;
			getline(infile, tmp);

			std::string name = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string password = tmp;

			librarians.push_back(new Librarian(name, password));
		}
		
		//Beolvassuk a könyv adatait.
		std::string numberOfBooksTemp;
		getline(infile, numberOfBooksTemp);
		numberOfBooks = atoi(numberOfBooksTemp.c_str());

		for (int i = 0; i < numberOfBooks; ++i)
		{
			std::string tmp;
			getline(infile, tmp);

			std::string author = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string title = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string publisher = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			int year = atoi(tmp.substr(0, tmp.find(';')).c_str());

			tmp = tmp.substr(tmp.find(';') + 1);
			int edition = atoi(tmp.substr(0, tmp.find(';')).c_str());

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string ISBN = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			int borrowableAmount = atoi(tmp.c_str());

			books.push_back(new Book(author,title,publisher,year,edition,ISBN,borrowableAmount));
		}

		//Beolvassuk a tagok adatait.
		std::string numberOfMembersTemp;
		getline(infile, numberOfMembersTemp);
		numberOfMembers = atoi(numberOfMembersTemp.c_str());

		for (int i = 0; i < numberOfMembers; ++i)
		{
			std::string tmp;
			getline(infile, tmp);

			std::string name = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string address = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string type = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			std::string contacts = tmp.substr(0, tmp.find(';'));

			tmp = tmp.substr(tmp.find(';') + 1);
			int numberOfBorrowedBooks = atoi(tmp.substr(0, tmp.find(';')).c_str());

			//Beolvassuk a kölcsönzéseket tagonként.
			std::vector<Loaning*> booksBorrowed;
			for (int j = 0; j < numberOfBorrowedBooks; ++j)
			{
				tmp = tmp.substr(tmp.find(';') + 1);
				std::string dateOfBeginStr = tmp.substr(0, tmp.find(';'));
				Date dateofBegin(dateOfBeginStr);

				tmp = tmp.substr(tmp.find(';') + 1);
				std::string bookID = tmp.substr(0, tmp.find(';'));

				tmp = tmp.substr(tmp.find(';') + 1);
				std::string dateOfReturnStr = tmp.substr(0, tmp.find(';'));
				Date dateOfReturn(dateOfReturnStr);

				Loaning* loaning = new Loaning(dateofBegin, bookID, dateOfReturn);
				booksBorrowed.push_back(loaning);
			}

			//Típusuktól függően rakjuk bele a vektorba a tagokat.
			if (type == "St")
				members.push_back(new Student(name,address,type,contacts,booksBorrowed));
			
			else if (type == "Te")
				members.push_back(new Teacher(name,address,type,contacts,booksBorrowed));
			
			else if (type == "Ou")
				members.push_back(new OtherUnivCitizen(name,address,type,contacts,booksBorrowed));
			
			else if (type == "Ot")
				members.push_back(new Other(name,address,type,contacts,booksBorrowed));
		}

		//A könyvek borrowedBy vektorát is kitöltjük
		for (Member* e : members)
		{
			for (auto v : e->GetBooksBorrowed())
			{
				std::string tempBookID = v->bookID;
				//Kisbetűssé alakítjuk
				for (unsigned int i = 0; i < tempBookID.length(); ++i)
					tempBookID[i] = tolower(tempBookID[i]);

				Book* b = SearchBookByID(tempBookID);
				b->AddBorrower(e);
			}
		}
	}

	infile.close();
}


void Menu::Login()
{
	bool success = false;
	while (!success)
	{
		if (system("CLS")) system("clear");
		std::string username;
		std::string password; 
		std::cout << "Library Administration System\n"
			 	  << "-----------------------------\n"
			  	  << "Librarian's name: ";
		getline(std::cin, username);
		std::cout << "Password: ";
		getline(std::cin, password);
		std::string MD5OfPassword = md5(password);
	
		for (const Librarian* e : librarians)
		{
			if (username == e->name && MD5OfPassword == e->password)
				success = true;
		}
	}
}

void Menu::ShowMenu()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System\n"
	<< "-----------------------------\n"
	<< "1. Manage books...\n"
	<< "2. Manage members...\n"
	<< "3. Manage loanings...\n"
	<< "0. Exit" << std::endl;
}

void Menu::ShowBookMenu()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Manage books\n"
	<< "--------------------------------------------\n"
	<< "1. Add a new book\n"
	<< "2. List of books\n"
	<< "3. Search a book\n"
	<< "4. Delete a book\n"
	<< "0. Back to the main menu..." << std::endl;
}

void Menu::ShowMemberMenu()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Manage members\n"
	<< "----------------------------------------------\n"
	<< "1. Add a new member\n"
	<< "2. List of members\n"
	<< "3. Search a member\n"
	<< "4. Delete a member\n"
	<< "0. Back to the main menu..." << std::endl;
}

void Menu::ShowLoaningMenu()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Manage loanings\n"
	<< "-----------------------------------------------\n"
	<< "1. Add a new loaning\n"
	<< "2. Return a borrowed book\n"
	<< "0. Back to the main menu..." << std::endl;
}


void Menu::Run()
{
	std::string menu1, menu2;
	do {
		ShowMenu();
		getline(std::cin, menu1);

		switch (atoi(menu1.c_str()))
		{
			case 1: 
				do {
					ShowBookMenu(); 
					getline(std::cin, menu2);

					switch (atoi(menu2.c_str()))
					{
						case 1:
							AddNewBook();
							break;
						case 2:
							ListBooks();
							break;
						case 3:
							SearchBook();
							break;
						case 4: 
							DeleteBook();
							break;
					}

				} while (atoi(menu2.c_str()) != 0);
				break;

			case 2: 
				do {
					ShowMemberMenu(); 
					getline(std::cin, menu2);

					switch (atoi(menu2.c_str()))
					{
						case 1:
							AddNewMember();
							break;
						case 2:
							ListMembers();
							break;
						case 3:
							SearchMember();
							break;
						case 4: 
							DeleteMember();
							break;
					}

				} while (atoi(menu2.c_str()) != 0);
				break;

			case 3: 
				do {
					ShowLoaningMenu(); 
					getline(std::cin, menu2);

					switch (atoi(menu2.c_str()))
					{
						case 1:
							BorrowBook();
							break;
						case 2:
							ReturnBook();
							break;	   		
					}

				} while (atoi(menu2.c_str()) != 0);
				break;
		}

	} while(atoi(menu1.c_str()) != 0);
}

void Menu::SaveData()
{
	std::ofstream outfile;
	outfile.open("library.dat");

	//Írjuk ki a könyvtárosokat.
	outfile << librarians.size() << "\n";
	for (const Librarian* librarian : librarians)
		outfile << librarian->name << ";" << librarian->password << "\n";

	//Írjuk ki a könyveket.
	outfile << books.size() << "\n";
	for (const Book* book : books)
		outfile << book->GetAuthor() << ";" << book->GetTitle() << ";" << book->GetPublisher() << ";" << book->GetYear() 
				<< ";" << book->GetEdition() << ";" << book->GetISBN() << ";" << book->GetBorrowableAmount() << "\n";

	//Írjuk ki a tagokat.
	outfile << members.size() << "\n";
	for (const Member* member : members)
	{
		outfile << member->GetName() << ";" << member->GetAddress() << ";" << member->GetType() << ";" << member->GetContacts();
		std::vector<Loaning*> loanings = member->GetBooksBorrowed();
		outfile << ";" << loanings.size();
		for (const Loaning* loaning : loanings)
			outfile << ";" << loaning->dateOfBegin << ";" << loaning->bookID << ";" << loaning->dateOfReturn;

		outfile << "\n";
	}
}

void Menu::AddNewMember()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Add new member\n"
	<< "----------------------------------------------\n";
	std::string name, address, type, contacts;
	std::vector<Loaning*> booksBorrowed;

	std::cout << "Name: ";
	std::cin >> name;
	std::cout << "Address: ";
	std::cin >> address;
	std::cout << "Type (St = Student, Te = Teacher, Ou = Other University Citizen, Ot = Other): ";
	std::cin >> type;
	if (!(type == "St" || type == "Te" || type == "Ou" || type == "Ot"))
	{
		std::cout << type << " is an invalid member type. Adding a new member failed.";
		std::cin.get();
		return;
	}
	std::cout << "Contacts: ";
	std::cin >> contacts;
	
	if (type == "St")
		members.push_back(new Student(name,address,type,contacts,booksBorrowed));

	else if (type == "Te")
		members.push_back(new Teacher(name,address,type,contacts,booksBorrowed));
	
	else if (type == "Ou")
		members.push_back(new OtherUnivCitizen(name,address,type,contacts,booksBorrowed));
	
	else if (type == "Ot")
		members.push_back(new Other(name,address,type,contacts,booksBorrowed));

	else 
	{
		std::cout << type << " is not a valid type!\n";
		return;
	}

	std::cout << "\n\nThe member has been added to the database!";
	std::cin.get();
}
 
void Menu::AddNewBook()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Add new book\n"
	<< "--------------------------------------------\n";
	std::string menu;
	std::cout << "1. Add new instances of an existing book\n"
	<< "2. Add a new book\n";
	getline(std::cin, menu);

	switch (atoi(menu.c_str()))
	{
		case 1:
		{
			std::string bookID; 
			std::string incAmount;
			std::cout << "Book ID: ";
			std::cin >> bookID;
			std::cout << "Amount of new instances: ";
			getline(std::cin, incAmount);

			if (atoi(incAmount.c_str()) <= 0)
			{
				std::cout << "Incorrect amount! You can only add positive amount of new instances. ";
				break;
			}

			//Kisbetűssé alakítjuk a kereséshez az ID-t
			for (unsigned int i = 0; i < bookID.length(); ++i)
				bookID[i] = tolower(bookID[i]);

			Book* book = SearchBookByID(bookID);
			if (book)
				book->IncBorrowableAmount(atoi(incAmount.c_str()));

			else 
				std::cout << "\nBook not found with this ID! ";
		}
		break;
		case 2:
		{
			std::string author, title, publisher, year, edition, ISBN, borrowableAmount;
			std::cout << "Author: ";
			std::cin >> author;
			std::cout << "Title: ";
			std::cin >> title;
			std::cout << "Publisher: ";
			std::cin >> publisher;
			std::cout << "Year: ";
			std::cin >> year;
			if (!(atoi(year.c_str()) >= 1900 && atoi(year.c_str()) <= 2100))
			{
				std::cout << year << " is an invalid year. Valid years are between 1900 and 2100.";
				break;
			}
			std::cout << "Edition: ";
			std::cin >> edition;
			std::cout << "ISBN: ";
			std::cin >> ISBN;
			if (!(ISBN.length() == 10 || ISBN.length() == 13))
			{
				std::cout << year << " is an invalid ISBN. Valid ISBN numbers contain 10 or 13 digits.";
				break;
			}
			std::cout << "Borrowable amount: ";
			std::cin >> borrowableAmount;
			if (atoi(borrowableAmount.c_str()) <= 0)
			{
				std::cout << year << " is an invalid amount. Only positive numbers are valid.";
				break;
			}
			
			books.push_back(new Book(author, title, publisher, atoi(year.c_str()), atoi(edition.c_str()), ISBN, atoi(borrowableAmount.c_str())));
			std::cout << "\n\nThe book has been added to the database!";
		}
		break;
	}

	std::cin.get();
}


void Menu::ListMembers()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - List of members\n"
	<< "-----------------------------------------------\n";
	
	for (const Member* member : members)
	{
		std::cout << member;
		std::cout << "\n"; 
	}

	std::cin.get();
}

void Menu::ListBooks()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - List of books\n"
	<< "---------------------------------------------\n";
	
	for (const Book* book : books)
	{
		std::cout << book;
		std::cout << "Borrowers of this book:\n";
		std::vector<Member*> borrowedBy = book->GetBorrowedBy();
		for (Member* member : borrowedBy)
			std::cout << "ID: " << member->GetID() << "   Name: " << member->GetName() << "\n";
		std::cout << "\n";
	}

	std::cin.get();
}

void Menu::SearchMember()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Search a member\n"
	<< "-----------------------------------------------\n";
	std::string menu;
	std::cout << "1. Search a member by ID\n"
	<< "2. Search a member by name\n";
	getline(std::cin, menu);
	Member* mem = nullptr; //Ha módosítani akarja a könyvtáros az attribútumait, akkor át kell adni paraméterként a megtalált tagot.

	switch (atoi(menu.c_str()))
	{
		case 1:
		{
			std::string memberID; 
			std::cout << "Member's ID: ";
			std::cin >> memberID;
			//Kisbetűssé alakítjuk
			for (unsigned int i = 0; i < memberID.length(); ++i)
				memberID[i] = tolower(memberID[i]);

			Member* member;
			member = SearchMemberByID(memberID);
			mem = member;
			if (member)
				std::cout << member;
			else 
				std::cout << "\nMember not found with this ID! ";
		}
		std::cin.get();
		break;
		case 2:
		{
			std::string memberName; 
			std::cout << "Member's name: ";
			getline(std::cin, memberName);
			//Kisbetűssé alakítjuk
			for (unsigned int i = 0; i < memberName.length(); ++i)
				memberName[i] = tolower(memberName[i]);

			bool foundMember = false;
			unsigned int i = 0;
			while (i<members.size() && !foundMember)
			{
				std::string nameTemp = members[i]->GetName();
				//Kisbetűssé alakítjuk
				for (unsigned int i = 0; i < nameTemp.length(); ++i)
					nameTemp[i] = tolower(nameTemp[i]);

				//A keresett nevet a tárolt név elejére illesztjük.
				if (nameTemp.compare(0,memberName.length(),memberName,0,memberName.length()) == 0)
				{
					std::cout << members[i];
					mem = members[i];
					foundMember = true;
				}
				++i;
			}
			if (!foundMember)
				std:: cout << "\nMember not found with this name!\n\n";			
		}
		std::cin.get();
		break;
	}

	std::string menu2;
	do{
		std::cout << "1. Modify this member\n"
		<< "0. Back to the members menu...\n";
		getline(std::cin, menu2);

		switch (atoi(menu2.c_str()))
		{
			case 1:
				ModifyMemberAttributes(mem);
				break;
			case 0: 
				break;
		}
	}while(atoi(menu2.c_str()) != 0);
}

void Menu::SearchBook()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Search a book\n"
	<< "---------------------------------------------\n";
	std::string menu;
	std::cout << "1. Search a book by ID\n"
	<< "2. Search a book by author\n"
	<< "3. Search a book by title\n"
	<< "4. Search a book by ISBN\n";
	getline(std::cin, menu);

	switch (atoi(menu.c_str()))
	{
		case 1:
		{
			std::string bookID; 
			std::cout << "Book ID: ";
			std::cin >> bookID;
			//Kisbetűssé alakítjuk
			for (unsigned int i = 0; i < bookID.length(); ++i)
				bookID[i] = tolower(bookID[i]);
	
			Book* book = SearchBookByID(bookID);
			if (book)
			{
				std::cout << book;
				std::cout << "Borrowers of this book:\n";
				std::vector<Member*> borrowedBy = book->GetBorrowedBy();
				for (Member* member : borrowedBy)
					std::cout << "ID: " << member->GetID() << "   Name: " << member->GetName() << "\n";
				std::cout << "\n";
			}
			else 
				std::cout << "\nBook not found with this ID! ";
		}
		std::cin.get();
		break;
		case 2:
		{
			std::string author; 
			std::cout << "Author of the book: ";
			getline(std::cin, author);
			//Kisbetűssé alakítjuk
			for (unsigned int i = 0; i < author.length(); ++i)
				author[i] = tolower(author[i]);
		
			bool foundBook = false;
			unsigned int i = 0;
			while (i<books.size() && !foundBook)
			{
				std::string authorTemp = books[i]->GetAuthor();
				//Kisbetűssé alakítjuk
				for (unsigned int i = 0; i < authorTemp.length(); ++i)
					authorTemp[i] = tolower(authorTemp[i]);

				//A keresett szerzőt a tárolt név elejére illesztjük.
				if (authorTemp.compare(0,author.length(),author,0,author.length()) == 0)
				{
					std::cout << books[i];
					std::cout << "Borrowers of this book:\n";
					std::vector<Member*> borrowedBy = books[i]->GetBorrowedBy();
					for (Member* member : borrowedBy)
						std::cout << "ID: " << member->GetID() << "   Name: " << member->GetName() << "\n";
					foundBook = true;
					std::cout << "\n";
				}
				++i;
			}
			if (!foundBook)
				std:: cout << "\nBook not found with this author! ";			
		}
		break;
		case 3:
		{
			std::string title; 
			std::cout << "Title of the book: ";
			getline(std::cin, title);
			//Kisbetűssé alakítjuk
			for (unsigned int i = 0; i < title.length(); ++i)
				title[i] = tolower(title[i]);

			bool foundBook = false;
			unsigned int i = 0;
			while (i<books.size() && !foundBook)
			{
				std::string titleTemp = books[i]->GetTitle();
				//Kisbetűssé alakítjuk
				for (unsigned int i = 0; i < titleTemp.length(); ++i)
					titleTemp[i] = tolower(titleTemp[i]);

				//A keresett címet a tárolt cím elejére illesztjük.
				if (titleTemp.compare(0,title.length(),title,0,title.length()) == 0)
				{
					std::cout << books[i];
					std::cout << "Borrowers of this book:\n";
					std::vector<Member*> borrowedBy = books[i]->GetBorrowedBy();
					for (Member* member : borrowedBy)
						std::cout << "ID: " << member->GetID() << "   Name: " << member->GetName() << "\n";
					foundBook = true;
					std::cout << "\n";
				}
				++i;
			}
			if (!foundBook)
				std:: cout << "\nBook not found with this title! ";			
		}
		break;
		case 4:
		{
			std::string ISBN; 
			std::cout << "ISBN of the book: ";
			std::cin >> ISBN;
			//Kisbetűssé alakítjuk
			for (unsigned int i = 0; i < ISBN.length(); ++i)
				ISBN[i] = tolower(ISBN[i]);

			bool foundBook = false;
			unsigned int i = 0;
			while (i<books.size() && !foundBook)
			{
				std::string ISBNTemp = books[i]->GetISBN();
				//Kisbetűssé alakítjuk
				for (unsigned int i = 0; i < ISBNTemp.length(); ++i)
					ISBNTemp[i] = tolower(ISBNTemp[i]);

				//A keresett ISBN-t a tárolt név elejére illesztjük.
				if (ISBNTemp.compare(0,ISBN.length(),ISBN,0,ISBN.length()) == 0)
				{
					std::cout << books[i];
					std::cout << "Borrowers of this book:\n";
					std::vector<Member*> borrowedBy = books[i]->GetBorrowedBy();
					for (Member* member : borrowedBy)
						std::cout << "ID: " << member->GetID() << "   Name: " << member->GetName() << "\n";
					std::cout << "\n";
					foundBook = true;
				}
				++i;
			}
			if (!foundBook)
				std:: cout << "\nBook not found with this ISBN! ";			
		}
		break;
	}

	std::cin.get();
}

void Menu::DeleteMember()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Delete a member\n"
	<< "-----------------------------------------------\n";
	std::string id;
	std::cout << "Member's ID: ";
	std::cin >> id;

	bool found = false;
	for (auto it = members.begin(); it != members.end() && !found;)
	{
	   	if ((*it)->GetID() == id && ((*it)->GetBooksBorrowed()).empty())
		{
			delete *it;  
	   		it = members.erase(it);
	  		found = true;
	  		std::cout << "Member with ID " << id << " has been deleted.";
	 	}
		else 
			++it;
	}
	
	if (!found) 
		std::cout << "Can't delete member with ID " << id << ", because the member is currently loaning a book, or member with this ID doesn't exist.";

	std::cin.get();
	std::cin.get();
}

void Menu::DeleteBook()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Delete a book\n"
	<< "---------------------------------------------\n";
	std::string id;
	std::cout << "Book's ID: ";
	std::cin >> id;

	bool found = false;
	for (auto it = books.begin(); it != books.end() && !found;)
	{
		if ((*it)->GetID() == id && ((*it)->GetBorrowedBy()).empty())
		{
			delete *it;  
			it = books.erase(it);
			found = true;
			std::cout << "Book with ID " << id << " has been deleted.";
		}
		else 
			++it;
	}
	
	if (!found) 
		std::cout << "Can't delete book with ID " << id << ", because a member is currently loaning it, or book with this ID doesn't exist.";

	std::cin.get();
	std::cin.get();
}

void Menu::ModifyMemberAttributes(Member* mem)
{
	if (!mem)
	{
		std::cout << "\nCan't modify a not found member.\n";
		std::cin.get();
		return;
	}

	std::string menu;
	do{
		if (system("CLS")) system("clear");

		std::cout << "Library Administration System - Modify a member\n"
		<< "-----------------------------------------------\n";
		std::cout << mem;
		std::cout << "\n1. Modify name\n"
		<< "2. Modify address\n"
		<< "3. Modify type\n"
		<< "4. Modify contacts\n"
		<< "0. Cancel\n";
		getline(std::cin, menu);

		std::string tmp;
		switch (atoi(menu.c_str()))
		{
			case 1:
				std::cout << "\nNew name: ";
				getline(std::cin, tmp);
				mem->SetName(tmp);
				std::cout << "Name has been set to " << tmp;
				break;
			case 2:
				std::cout << "\nNew address: ";
				getline(std::cin, tmp);
				mem->SetAddress(tmp);
				std::cout << "Address has been set to " << tmp;
				break;
			case 3:
				std::cout << "\nNew type: ";
				getline(std::cin, tmp);
				if (!(tmp == "St" || tmp == "Te" || tmp == "Ou" || tmp == "Ot"))
				{
					std::cout << tmp << " is an invalid member type. Modifying failed.";
					return;
				}
				mem->SetType(tmp);
				std::cout << "Type has been set to " << tmp;
				break;
			case 4:
				std::cout << "\nNew contacts: ";
				getline(std::cin, tmp);
				mem->SetContacts(tmp);
				std::cout << "Contacts has been set to " << tmp;
				break;
			case 0: 
				break;
		}
		std::cin.get();
	}while (atoi(menu.c_str()) != 0);
}

void Menu::BorrowBook()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Borrow a book\n"
	<< "---------------------------------------------\n";
	std::string bookID, memberID, year, month, day;
	std::cout << "Book's ID: ";
	std::cin >> bookID;
	std::cout << "Member's ID: ";
	std::cin >> memberID;
	std::cout << "Date of beginning (YYYY MM DD): ";
	std::cin >> year >> month >> day;
	Date dateOfBegin(year,month,day);

	if (!dateOfBegin.IsValidDate() || atoi(year.c_str()) < 1900 || atoi(year.c_str()) > 2100)
	{
		std::cout << "Invalid date. Valid years are between 1900 and 2100. Valid months are between 1 and 12. Valid days are between 1 and 31.";
		std::cin.get();
		std::cin.get();
		return;
	}

	//Kisbetűssé alakítjuk a kereséshez az ID-ket
	for (unsigned int i = 0; i < bookID.length(); ++i)
		bookID[i] = tolower(bookID[i]);
	for (unsigned int i = 0; i < memberID.length(); ++i)
		memberID[i] = tolower(memberID[i]);

	Member* member = SearchMemberByID(memberID);
	Book* book = SearchBookByID(bookID);

	//Hibakezelés - kódismétlődés elkerülése miatt itt ellenőrizzük az összes származtatott osztályra, nem külön-külön
	//A könyv és a tag ID-je helyes-e
	if (!(member && book))
	{
		std::cout << "\nBook with ID " << bookID << " or member with ID " << memberID << " doesn't exist.";
		std::cin.get();
		std::cin.get();
		return;
	}

	//Kivette-e már ezt a könyvet
	bool found = false;
	std::vector<Loaning*> booksBorrowed = member->GetBooksBorrowed();
	for (auto it = booksBorrowed.begin(); it != booksBorrowed.end() && !found; ++it)
	{
		std::string actBookID = (*it)->bookID;
		//Kisbetűssé alakítjuk az aktuális könyv ID-jét a keresés miatt
		for (unsigned int i = 0; i < actBookID.length(); ++i)
			actBookID[i] = tolower(actBookID[i]);
		
		if (actBookID == bookID)
			found = true;
	}
	if (found)
	{
		std::cout << "\nThis member is currently loaning the book.";
		std::cin.get();
		std::cin.get();
		return;
	}

	//A könyv kölcsönözhető-e még
	if (!book->IsBorrowable())
	{
		std::cout << "\nThe book is not borrowable.";
		std::cin.get();
		std::cin.get();
		return;
	}

	//Ha túljutottunk az összes hibán, akkor meghívhatjuk a kölcsönzést
	bool isBorrowSuccessful = member->Borrow(book, dateOfBegin);
	if (isBorrowSuccessful)
		std::cout << "New loaning has been added.";

	std::cin.get();
	std::cin.get();
}

void Menu::ReturnBook()
{
	if (system("CLS")) system("clear");

	std::cout << "Library Administration System - Return a book\n"
	<< "---------------------------------------------\n";
	std::string bookID, memberID, year, month, day;
	std::cout << "Book's ID: ";
	std::cin >> bookID;
	std::cout << "Member's ID: ";
	std::cin >> memberID;
	std::cout << "Date of returning (YYYY MM DD): ";
	std::cin >> year >> month >> day;

	Date dateOfReturn(year,month,day);

	if (!dateOfReturn.IsValidDate() || atoi(year.c_str()) < 1900 || atoi(year.c_str()) > 2100)
	{
		std::cout << "Invalid date. Valid years are between 1900 and 2100. Valid months are between 1 and 12. Valid days are between 1 and 31.";
		std::cin.get();
		std::cin.get();
		return;
	}

	//Kisbetűssé alakítjuk a kereséshez az ID-ket
	for (unsigned int i = 0; i < bookID.length(); ++i)
		bookID[i] = tolower(bookID[i]);
	for (unsigned int i = 0; i < memberID.length(); ++i)
		memberID[i] = tolower(memberID[i]);

	Member* member = SearchMemberByID(memberID);
	Book* book = SearchBookByID(bookID);

	//Hibakezelés - a ReturnBook() metódus miatt a menüben implementálva, a metóduson belül nem tudunk hiba esetén értelmes visszatérési értéket adni.
	//A könyv és a tag ID-je helyes-e
	if (!(member && book))
	{
		std::cout << "\nBook with ID " << bookID << " or member with ID " << memberID << " doesn't exist.";
		std::cin.get();
		std::cin.get();
		return;
	}

	//Kivette-e ezt a könyvet
	bool found = false;
	std::vector<Loaning*> booksBorrowed = member->GetBooksBorrowed();
	for (auto it = booksBorrowed.begin(); it != booksBorrowed.end() && !found; ++it)
	{
		std::string actBookID = (*it)->bookID;
		//Kisbetűssé alakítjuk az aktuális könyv ID-jét a keresés miatt
		for (unsigned int i = 0; i < actBookID.length(); ++i)
			actBookID[i] = tolower(actBookID[i]);
		
		if (actBookID == bookID)
			found = true;
	}
	if (!found)
	{
		std::cout << "\nThis member is not loaning the book.";
		std::cin.get();
		std::cin.get();
		return;
	}

	bool isBeforeDueDate = member->ReturnBook(book, dateOfReturn);
	std::cout << "\nThe book has been successfully returned.\n";
	if (isBeforeDueDate)
		std::cout << "The member has returned the book before due date.\n";
	else
		std::cout << "The member has returned the book after due date.\n";
	
	std::cin.get();
}

Member* Menu::SearchMemberByID(std::string id)
{
	for (Member* e : members)
	{
		std::string IDTemp = e->GetID();
		//Kisbetűssé alakítjuk.
		for (unsigned int i = 0; i < IDTemp.length(); ++i)
			IDTemp[i] = tolower(IDTemp[i]);

		//A feltételt a szöveg elejére illesztjük.
		if (IDTemp.compare(0,id.length(),id,0,id.length()) == 0)
			return e;
	}
	return nullptr;
}

Book* Menu::SearchBookByID(std::string id)
{
	for (Book* e : books)
	{
		std::string IDTemp = e->GetID();
		//Kisbetűssé alakítjuk
		for (unsigned int i = 0; i < IDTemp.length(); ++i)
			IDTemp[i] = tolower(IDTemp[i]);

		//A feltételt a szöveg elejére illesztjük.
		if (IDTemp.compare(0,id.length(),id,0,id.length()) == 0)
			return e;
	}
	return nullptr;
}

Menu::~Menu()
{
	for (Librarian* l : librarians)
		delete l;

	for (Book* b : books)
		delete b;

	for (Member* m : members)
		delete m;
}

#endif
